﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * ZIP Central Directory End Record Class
 * 		Represents and manages the end-of-central-directory record.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.IO;

namespace Adaptive.Foundation.IO.Zip
{

	/// <summary>
	/// Represents and manages the end-of-central-directory record.
	/// </summary>
	public sealed class ZipCentralDirectoryEndRecord : ZipIoBase
	{
		/*--------------------------------------------------------------------------------
		 * Private Member Declarations
		 *------------------------------------------------------------------------------*/
		#region Private Member Declarations
		/// <summary>
		/// Item signature value.
		/// </summary>
		private byte[] _signature = new byte[] { 80, 75, 5, 6 };
		/// <summary>
		/// Number of the diskette when spanning.
		/// </summary>
		private short _diskNumber;
		/// <summary>
		/// Number of the first diskette when spanning.
		/// </summary>
		private short _diskNumberStart;
		/// <summary>
		/// Number of entries on the diskette when spanning.
		/// </summary>
		private short _totalEntriesOnDisk;
		/// <summary>
		/// Number of entries in the directory.
		/// </summary>
		private short _totalEntries;
		/// <summary>
		/// Byte size of the directory.
		/// </summary>
		private int _directorySize;
		/// <summary>
		/// Byte offset of the directory start.
		/// </summary>
		private int _directoryOffset;
		/// <summary>
		/// Length of the zip file comment.
		/// </summary>
		private short _zipFileCommentLength;
		/// <summary>
		/// The comment.
		/// </summary>
		private string _zipFileComment = String.Empty;
		#endregion

		/*--------------------------------------------------------------------------------
		 * Constructor / Dispose / Destructor Methods
		 *------------------------------------------------------------------------------*/
		#region Constructor / Dispose / Destructor Methods
		/// <summary>
		/// Initializes a new instance of the <see cref="ZipCentralDirectoryEndRecord" /> class.
		/// </summary>
		/// <remarks>
		/// This is the default constructor.
		/// </remarks>
		public ZipCentralDirectoryEndRecord()
			: base()
		{
		}
		/// <summary>
		/// Releases unmanaged and - optionally - managed resources
		/// </summary>
		/// <param name="disposing"><b>true</b> to release both managed and unmanaged resources;
		/// <b>false</b> to release only unmanaged resources.</param>
		protected override void Dispose(bool disposing)
		{
			_signature = null;
			_zipFileComment = null;
			base.Dispose(disposing);
		}
		#endregion

		/*--------------------------------------------------------------------------------
		 * Public Properties
		 *------------------------------------------------------------------------------*/
		#region Public Properties
		/// <summary>
		/// Gets or sets the number of the diskette when spanning.
		/// </summary>
		/// <value>
		/// The spanning disk number or zero(0).
		/// </value>
		public short DiskNumber
		{
			get
			{
				return _diskNumber;
			}
			set
			{
				_diskNumber = value;
			}
		}
		/// <summary>
		/// Gets or sets the number of the first diskette when spanning.
		/// </summary>
		/// <value>The disk number start or zero (0).</value>
		public short DiskNumberStart
		{
			get
			{
				return _diskNumberStart;
			}
			set
			{
				_diskNumberStart = value;
			}
		}
		/// <summary>
		/// Gets or sets the total entries on disk.
		/// </summary>
		/// <value>The the number of entries on the diskette when spanning.</value>
		public short TotalEntriesOnDisk
		{
			get
			{
				return _totalEntriesOnDisk;
			}
			set
			{
				_totalEntriesOnDisk = value;
			}
		}
		/// <summary>
		/// Gets or sets the number of total entries.
		/// </summary>
		/// <value>The the number of entries in the directory.</value>
		public short TotalEntries
		{
			get
			{
				return _totalEntries;
			}
			set
			{
				_totalEntries = value;
			}
		}
		/// <summary>
		/// Gets or sets the size of the directory.
		/// </summary>
		/// <value>The size of the directory, in bytes.</value>
		public int DirectorySize
		{
			get
			{
				return _directorySize;
			}
			set
			{
				_directorySize = value;
			}
		}
		/// <summary>
		/// Gets or sets the directory offset byte location.
		/// </summary>
		/// <value>The directory offset value.</value>
		public int DirectoryOffset
		{
			get
			{
				return _directoryOffset;
			}
			set
			{
				_directoryOffset = value;
			}
		}
		/// <summary>
		/// Gets the length of the zip file comment.
		/// </summary>
		/// <value>The length of the zip file comment.</value>
		public short ZipFileCommentLength
		{
			get
			{
				return _zipFileCommentLength;
			}
		}
		/// <summary>
		/// Gets or sets the zip file comment.
		/// </summary>
		/// <value>The zip file comment value.</value>
		public string ZipFileComment
		{
			get
			{
				return _zipFileComment;
			}
			set
			{

				if (String.IsNullOrEmpty(value))
				{
					_zipFileCommentLength = 0;
					_zipFileComment = String.Empty;
				}
				else
				{
					_zipFileComment = value;
					_zipFileCommentLength = Convert.ToInt16(value.Length);
				}
			}
		}
		#endregion

		/*--------------------------------------------------------------------------------
		 * Public Methods / Functions
		 *------------------------------------------------------------------------------*/
		#region "Public Methods / Functions"
		/// <summary>
		/// Resets the property values for all items in the instance to their default values, and
		/// clears any internal lists or collections.
		/// </summary>
		public override void Clear()
		{
			_signature = new Byte[] { 80, 75, 5, 6 };
			_diskNumber = 0;
			_diskNumberStart = 0;
			_totalEntriesOnDisk = 0;
			_totalEntries = 0;
			_directorySize = 0;
			_directoryOffset = 0;
			_zipFileCommentLength = 0;
			_zipFileComment = String.Empty;
			base.Clear();
		}
		/// <summary>
		/// Loads the content for the instance from the specified stream.
		/// </summary>
		/// <param name="reader">An open <see cref="BinaryReader" /> used to read data from the
		/// underlying stream.</param>
		/// <returns>
		/// <b>true</b> if the load operation is successful; otherwise, <b>false</b>.
		/// </returns>
		public override bool Load(BinaryReader reader)
		{
			bool returnValue = false;				//Return value.

			try
			{

				_signature = reader.ReadBytes(4);
				_diskNumber = reader.ReadInt16();
				_diskNumberStart = reader.ReadInt16();
				_totalEntriesOnDisk = reader.ReadInt16();
				_totalEntries = reader.ReadInt16();
				_directorySize = reader.ReadInt32();
				_directoryOffset = reader.ReadInt32();
				_zipFileCommentLength = reader.ReadInt16();
				_zipFileComment =
					System.Text.ASCIIEncoding.ASCII.GetString(reader.ReadBytes(_zipFileCommentLength));

				returnValue = true;
			}
			catch (IOException)
			{
			}
			return returnValue;
		}
		/// <summary>
		/// Saves the content for the instance to the specified stream.
		/// </summary>
		/// <param name="writer">An open <see cref="BinaryWriter" /> used to write data to the
		/// underlying stream.</param>
		/// <returns>
		/// <b>true</b> if the save operation is successful; otherwise, <b>false</b>.
		/// </returns>
		public override bool Save(BinaryWriter writer)
		{
			bool returnValue = false;				//Return value.

			try
			{
				writer.Write(_signature);
				writer.Write(_diskNumber);
				writer.Write(_diskNumberStart);
				writer.Write(_totalEntriesOnDisk);
				writer.Write(_totalEntries);
				writer.Write(_directorySize);
				writer.Write(_directoryOffset);
				writer.Write(_zipFileCommentLength);
				writer.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(_zipFileComment));
				writer.Flush();

				returnValue = true;
			}
			catch (IOException)
			{
			}
			return returnValue;
		}
		#endregion
	}
}